do
    local setmetatable  = GLOBAL.setmetatable
    local rawget        = GLOBAL.rawget
    local G             = GLOBAL
    setmetatable(env, { __index = function(t, k) return rawget(G, k) end })
end

PrefabFiles = {
	"oa_colourpen", 
    "oa_penlight",
    "oa_penlightfire",
}

Assets = {
	Asset("ANIM", "anim/oa_player_attack_prop.zip"),
}

--四色圆珠笔
STRINGS.NAMES.OA_COLOURPEN = "四色圆珠笔"    --名字
STRINGS.RECIPE_DESC.OA_COLOURPEN = "一支巨大的圆珠笔"  --配方上面的描述
STRINGS.CHARACTERS.GENERIC.DESCRIBE.OA_COLOURPEN = "我已经怒不可遏了"  --人物检查的描述


AddRecipe("oa_colourpen",  --添加物品的配方
{Ingredient("featherpencil", 1)},  
RECIPETABS.WAR,  TECH.SCIENCE_TWO,  
nil, nil, nil, nil, nil,  
"images/weapons/oa_colourpen.xml",  --贴图.xml
"oa_colourpen.tex")  --贴图.tex

--荧光棒
STRINGS.NAMES.OA_PENLIGHT= "荧光棒"
STRINGS.RECIPE_DESC.OA_PENLIGHT = "可以照明的武器"  --配方上面的描述
STRINGS.CHARACTERS.GENERIC.DESCRIBE.OA_PENLIGHT = "我已经怒不可遏了"

AddRecipe("oa_penlight",  --添加物品的配方
{Ingredient("lantern", 1),Ingredient("lightninggoathorn", 1)},  --材料
RECIPETABS.WAR,  TECH.SCIENCE_TWO,  
nil, nil, nil, nil, nil, 
"images/weapons/oa_penlight.xml",  --贴图.xml
"oa_penlight.tex")  --贴图.tex




--- 新的攻击动作
local function HookAttack(self)
    local state = self.states.attack
    if state ~= nil then
        local old_onenter = state.onenter 
        state.onenter = function(inst, ...)
            local weapon = inst.replica.combat ~= nil and inst.replica.combat:GetWeapon()
            local riding = inst.replica.rider ~= nil and inst.replica.rider:IsRiding()
            if weapon ~= nil and not riding then
                local prefab = weapon.prefab
                if prefab  == "oa_colourpen" then -- 四色圆珠笔 慢速重击
                    inst.sg:GoToState("oa_slowattack")
                    return
                end
            end

            return old_onenter(inst, ...)
        end
    end
end

AddStategraphPostInit("wilson", HookAttack)
AddStategraphPostInit("wilson_client", HookAttack)

local PRE_MULT = 1
local ATK_MULT = 2
local PST_MULT = 3

AddStategraphState("wilson", State{
    -- 修改自 "attack"
    name = "oa_slowattack",
    tags = { "attack", "notalking", "abouttoattack", "autopredict" },

    onenter = function(inst)
        if inst.components.combat:InCooldown() then
            inst.sg:RemoveStateTag("abouttoattack")
            inst:ClearBufferedAction()
            inst.sg:GoToState("idle", true)
            return
        end
            
        local buffaction = inst:GetBufferedAction()
        local target = buffaction ~= nil and buffaction.target or nil
        inst.components.combat:SetTarget(target)
        inst.components.combat:StartAttack()
        inst.components.locomotor:Stop()

        inst.components.oa_weaponshadow:Start()

        inst.AnimState:PlayAnimation("oa_atk_prop_pre_4x")
        inst.AnimState:PushAnimation("oa_atk_prop_4x", false)
        inst.AnimState:SetDeltaTimeMultiplier(PRE_MULT) -- 设置动画播放速度

        -- inst.SoundEmitter:PlaySound("dontstarve/common/whip_pre", nil, nil, true)

        inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh", nil, nil, true)
    end,


    timeline =
    {
        TimeEvent(22 * FRAMES / PRE_MULT, function(inst)
            inst.AnimState:SetDeltaTimeMultiplier(ATK_MULT)
            inst.sg:AddStateTag("busy")
            inst.components.oa_weaponshadow:Start()
            inst.SoundEmitter:PlaySound("dontstarve/characters/woodie/moose/punch", nil, nil, true)
        end),

        TimeEvent(0.9, function(inst)
            inst:PerformBufferedAction()
            inst.sg:RemoveStateTag("abouttoattack")

        end),

        TimeEvent(1.3, function(inst)
            inst.AnimState:SetDeltaTimeMultiplier(PST_MULT)
            inst.components.oa_weaponshadow:Stop()
        end),
    },

    ontimeout = function(inst)
        inst.sg:RemoveStateTag("attack")
        inst.sg:AddStateTag("idle")
    end,

    events =
    {
        EventHandler("equip", function(inst) inst.sg:GoToState("idle") end),
        EventHandler("unequip", function(inst) inst.sg:GoToState("idle") end),
        EventHandler("animqueueover", function(inst)
            if inst.AnimState:AnimDone() then
                inst.sg:GoToState("idle")
            end
        end),
    },

    onexit = function(inst)
        inst.components.combat:SetTarget(nil)
        inst.components.oa_weaponshadow:Stop()
        inst.AnimState:SetDeltaTimeMultiplier(1)

        if inst.sg:HasStateTag("abouttoattack") then
            inst.components.combat:CancelAttack()
        end
    end,
})

AddStategraphState("wilson_client", State{
    name = "oa_slowattack",
    tags = { "attack", "notalking", "abouttoattack", "autopredict" },

    onenter = function(inst)
    	local buffaction = inst:GetBufferedAction()
        if inst.replica.combat ~= nil then
            if inst.replica.combat:InCooldown() then
                inst.sg:RemoveStateTag("abouttoattack")
                inst:ClearBufferedAction()
                inst.sg:GoToState("idle", true)
                return
            end
            inst.replica.combat:StartAttack()
        end
        
        inst.components.locomotor:Stop()
        
        if buffaction ~= nil then
            inst:PerformPreviewBufferedAction()

            if buffaction.target ~= nil and buffaction.target:IsValid() then
                inst:FacePoint(buffaction.target:GetPosition())
                inst.sg.statemem.attacktarget = buffaction.target
            end
        end

        inst.components.oa_weaponshadow:Start()

        inst.AnimState:PlayAnimation("oa_atk_prop_pre_4x")
        inst.AnimState:PushAnimation("oa_atk_prop_4x", false)
        inst.AnimState:SetDeltaTimeMultiplier(PRE_MULT) -- 设置动画播放速度

        -- inst.SoundEmitter:PlaySound("dontstarve/common/whip_pre", nil, nil, true)

        inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh", nil, nil, true)

        inst.sg:SetTimeout(1)
    end,


    timeline =
    {
        TimeEvent(22 * FRAMES / PRE_MULT, function(inst)
            inst.AnimState:SetDeltaTimeMultiplier(ATK_MULT)
            inst.sg:AddStateTag("busy")
            inst.components.oa_weaponshadow:Start()
            inst.SoundEmitter:PlaySound("dontstarve/characters/woodie/moose/punch", nil, nil, true)
        end),

        TimeEvent(0.9, function(inst)
            inst:ClearBufferedAction()
            inst.sg:RemoveStateTag("abouttoattack")

        end),

        TimeEvent(1.3, function(inst)
            inst.AnimState:SetDeltaTimeMultiplier(PST_MULT)
            inst.components.oa_weaponshadow:Stop()
        end),
    },

    ontimeout = function(inst)
        inst.sg:RemoveStateTag("attack")
        inst.sg:AddStateTag("idle")
    end,

    events =
    {
        EventHandler("animqueueover", function(inst)
            if inst.AnimState:AnimDone() then
                inst.sg:GoToState("idle")
            end
        end),
    },

    onexit = function(inst)
        inst.components.oa_weaponshadow:Stop()
        inst.AnimState:SetDeltaTimeMultiplier(1)

        if inst.sg:HasStateTag("abouttoattack") and inst.replica.combat ~= nil then
            inst.replica.combat:CancelAttack()
        end
    end,
})

-- 武器残影
local ALPHA = 0.2

AddPlayerPostInit(function(inst) 
    inst:AddComponent("oa_weaponshadow") 
    inst.components.oa_weaponshadow.shadow_per_frame = 1--0.34
    inst.components.oa_weaponshadow:SetSpawnPrefabFn(function()
        local ent = CreateEntity()
        local trans = ent.entity:AddTransform()
        local anim = ent.entity:AddAnimState()

        trans:SetFourFaced()
        trans:SetPosition(inst.Transform:GetWorldPosition())
        trans:SetRotation(inst.Transform:GetRotation())

        anim:SetBank("wilson")
        anim:SetBuild("oa_colourpen")
        anim:Show("ARM_carry")
        anim:Hide("ARM_normal")

        local animname = nil
        for i,v in ipairs{"oa_atk_prop_pre_4x", "oa_atk_prop_lag_4x", "oa_atk_prop_4x"}do
            if inst.AnimState:IsCurrentAnimation(v) then
                animname = v
                break                
            end
        end
        if animname then
            -- anim:PlayAnimation(animname)
            -- anim:SetTime(inst.AnimState:GetCurrentAnimationTime()-0.5*FRAMES)
            -- anim:Pause()
            anim:SetPercent(animname, (inst.AnimState:GetCurrentAnimationTime() - 0.5*FRAMES) / inst.AnimState:GetCurrentAnimationLength())
        end

        ent:AddComponent("colourtweener")
        -- ent.AnimState:SetAddColour(1,1,1,0)
        ent.AnimState:SetMultColour(ALPHA,ALPHA,ALPHA,ALPHA)
        ent.components.colourtweener:StartTween({0,0,0,0}, 5*FRAMES, ent.Remove)

        ent.entity:SetPristine()

        ent.persists = false


        return ent
    end)
end)